package com.unittec.drainage.gateway.filter;

import com.unittec.drainage.gateway.common.GateWayConstants;
import com.unittec.drainage.gateway.common.GatewayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.post.SendErrorFilter;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import com.netflix.zuul.context.RequestContext;
import com.unittec.drainage.provider.log.Log;
import com.unittec.drainage.sdk.root.common.FieldConstants;
import com.unittec.drainage.sdk.root.domain.GatewayRequest;
import com.unittec.drainage.sdk.root.domain.Result;
import com.unittec.drainage.sdk.root.enums.BizCode;
import com.unittec.drainage.sdk.root.internal.utils.SdkUtils;

@Component
public class GatewayErrorFilter extends SendErrorFilter {

    @Autowired
    Log log;

    @Value("${error.path:/error}")
    private String errorPath;

    private Throwable getCause(Throwable root) {
        if (null == root.getCause()) {
            return root;
        } else {
            return getCause(root.getCause());
        }
    }

    @Override
    public Object run() {

        try {
            RequestContext ctx = RequestContext.getCurrentContext();
            ExceptionHolder exception = findZuulException(ctx.getThrowable());

            Throwable cause = getCause(ctx.getThrowable());
            String errMsg = cause.toString();
            if (cause instanceof java.net.SocketTimeoutException || cause instanceof java.util.concurrent.TimeoutException) {
                errMsg = "处理超时";
            }

            if (StringUtils.isNotBlank(exception.getErrorCause())) {
                GatewayUtils.writer(ctx.getResponse(), SdkUtils.toJSON(Result
                    .getewayError((GatewayRequest)ctx.get(GateWayConstants.SERVICECONTENT), BizCode.ERROR, errMsg)));
            } else {
                GatewayUtils.writer(ctx.getResponse(), SdkUtils.toJSON(Result
                    .getewayError((GatewayRequest)ctx.get(GateWayConstants.SERVICECONTENT), BizCode.ERROR, errMsg)));
            }

            ctx.set(SEND_ERROR_FILTER_RAN, true);

            long startTime = (Long)ctx.get(GateWayConstants.REQ_START_TIME);
            GatewayRequest req = (GatewayRequest)ctx.get(GateWayConstants.SERVICECONTENT);

            if (null != req) {
                String token = ctx.getZuulRequestHeaders().get(FieldConstants.REQ_AUTHORIZATION.toLowerCase());
                req.setToken(token);
                log.error(req, "req id【{}】 cost time is 【{}】 ms, exception is 【{}】", req.getRequestId(),
                    (System.currentTimeMillis() - startTime), log.buildErrmsg(ctx.getThrowable()));
            }

        } catch (Exception ex) {
            ReflectionUtils.rethrowRuntimeException(ex);
        }

        return null;
    }
}
